﻿//-----------------------------------------------------------------------------
// File: TabSplitter.cs
//
// Copyright (c) Dmitry Shuklin. All rights reserved.
//-----------------------------------------------------------------------------
#region Usiug-и
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Text;
using Cerebrum.Direct3D.Forms;
#endregion

namespace Cerebrum.Direct3D.Forms
{
    #region Для события RenderSplitter
    /// <summary>
    /// Класс RenderSplitterEventArgs
    /// </summary>
    public class RenderSplitterEventArgs : Cerebrum.Direct3D.Forms.RenderEventArgs
    {
		private int m_SplitterIndex;
		private System.Drawing.RectangleF m_SplitterRectangle;

		public RenderSplitterEventArgs(Microsoft.DirectX.Direct3D.Device device, RectangleF clipRectangle, int splitterIndex, System.Drawing.RectangleF splitterRectangle)
            : base(device, clipRectangle)
        {
			m_SplitterIndex = splitterIndex;
			m_SplitterRectangle = splitterRectangle;
        }

        /// <summary>
        /// Прямоугольник сплиттера
        /// </summary>
        public System.Drawing.RectangleF SplitterRectangle
        {
            /*set
            {
				m_SplitterRectangle = value;
            }*/
            get
            {
				return m_SplitterRectangle;
            }
        }

        /// <summary>
        /// Номер сплиттера
        /// </summary>
        public int SplitterIndex
        {
			/*set
			{
				m_SplitterIndex = value;
			}*/
			get
            {
				return m_SplitterIndex;
            }
        }
    }

    public delegate void RenderSplitterEventHandler(object sender, RenderSplitterEventArgs ea);
    #endregion

    #region Для события UpdateSplitter
    /// <summary>
    /// Класс DeviceSplitterEventArgs
    /// </summary>
    public class UpdateSplitterEventArgs : Cerebrum.Direct3D.Forms.DeviceEventArgs
    {
		private int m_SplitterIndex;
		private System.Drawing.RectangleF m_SplitterRectangle;

		public UpdateSplitterEventArgs(Microsoft.DirectX.Direct3D.Device device, int splitterIndex, System.Drawing.RectangleF splitterRectangle)
            : base(device)
        {
			m_SplitterIndex = splitterIndex;
			m_SplitterRectangle = splitterRectangle;
		}

        /// <summary>
        /// Прямоугольник сплиттера
        /// </summary>
		public System.Drawing.RectangleF SplitterRectangle
        {
            /*set
            {
				m_SplitterRectangle = value;
            }*/
            get
            {
				return m_SplitterRectangle;
            }
        }

        /// <summary>
        /// Номер сплиттера
        /// </summary>
		public int SplitterIndex
        {
            /*set
            {
				m_SplitterIndex = value;
            }*/
            get
            {
				return m_SplitterIndex;
            }
        }
    }

    public delegate void UpdateSplitterEventHandler(object sender, UpdateSplitterEventArgs ea);
    #endregion

    #region Для события ControlPosition
    public class ControlPositionEventArgs : System.EventArgs
    {
        private float m_TabSplitterMinSize;

        public ControlPositionEventArgs(float TabSplitterMinSize)
        {
            m_TabSplitterMinSize = TabSplitterMinSize;
        }

        public float TabSplitterMinSize
        {
            set
            {
                m_TabSplitterMinSize = value;
            }
            get
            {
                return m_TabSplitterMinSize;
            }
        }
    }

    public delegate void ControlPositionEventHandler(object sender, ControlPositionEventArgs ea);
    #endregion

    /// <summary>
    /// Элемент управления TabSplitter
    /// </summary>
    public class TabSplitter : Cerebrum.Direct3D.Forms.TabPage // Cerebrum.Windows.Forms.TabPage
    {
        #region Класс ControlSettings
        private class ControlSettings
        {
            private Cerebrum.Direct3D.Forms.Control m_Ctrl;
            private float m_Alpha;
            private float m_MinSize;

            public ControlSettings(Cerebrum.Direct3D.Forms.Control Control, float amount)
            {
                m_Ctrl = Control;
                m_Alpha = amount;
                m_MinSize = 2;
            }

            public ControlSettings(Cerebrum.Direct3D.Forms.Control Control, float amount, float minSize)
            {
                m_Ctrl = Control;
                m_Alpha = amount;
                m_MinSize = minSize;
            }

            public Cerebrum.Direct3D.Forms.Control Control
            {
                set
                {
                    m_Ctrl = value;
                }
                get
                {
                    return m_Ctrl;
                }
            }

            public float Amount
            {
                set
                {
                    m_Alpha = value;
                }
                get
                {
                    return m_Alpha;
                }
            }

            public float MinSize
            {
                set
                {
                    m_MinSize = value;
                }
                get
                {
                    return m_MinSize;
                }
            }
        }
        #endregion

        #region Класс ControlsList
        private class ControlsList : ArrayList
        {
            private TabSplitter m_TabSplitter;

            public ControlsList(TabSplitter TabSplitter)
            {
                m_TabSplitter = TabSplitter;
            }

            /// <summary>
            /// Возвращает позицию элемента управления в зависимости от ориентации TabSplitter-а
            /// </summary>
            /// <param name="ctrl">Элемент управления</param>
            /// <returns>Его позиция</returns>
            public float GetPosition(Cerebrum.Direct3D.Forms.Control ctrl)
            {
                float pos;

				if (m_TabSplitter.LayoutDirection == LayoutDirection.Vertical)
                {
                    pos = ctrl.Location.Y;
                }
                else
                {
                    pos = ctrl.Location.X;
                }
                return pos;
            }

            /// <summary>
            /// Возвращает размер элемента управления в зависимости от ориентации TabSplitter-а
            /// </summary>
            /// <param name="ctrl">Элемент управления</param>
            /// <returns>Его размер</returns>
            public float GetSize(Cerebrum.Direct3D.Forms.Control ctrl)
            {
                float size;

				if (m_TabSplitter.LayoutDirection == LayoutDirection.Vertical)
                {
                    size = ctrl.Size.Height;
                }
                else
                {
                    size = ctrl.Size.Width;
                }
                return size;
            }

            /// <summary>
            /// Устанавливает элемент управления в заданную позицию и задаёт ему нужный размер
            /// </summary>
            /// <param name="position">Позиция элемента управления</param>
            /// <param name="size">Размер</param>
            public void SetBounds(Cerebrum.Direct3D.Forms.Control ctrl, float position, float size)
            {
				if (m_TabSplitter.LayoutDirection == LayoutDirection.Vertical)
                {
                    ctrl.SetBounds(0, position, m_TabSplitter.Size.Width, size, BoundsSpecified.All);
                }
                else
                {
                    ctrl.SetBounds(position, 0, size, m_TabSplitter.Size.Height, BoundsSpecified.All);
                }
            }

            /// <summary>
            /// Пересчёт размеров и коефициентов элементов управления после добавления нового элемента управления.
            /// </summary>
            /// <param name="addedCtrl">Добавляемый элемент управления.</param>
            public void RecalcAddControl(Cerebrum.Direct3D.Forms.Control addedCtrl)
            {
                float amendment;
                float alphaSum;
                float allSize;
                float normSize;
                float amount;
                float newSize;
                float ctrlSize;
                float position;
                Cerebrum.Direct3D.Forms.Control ctrl;

                try
                {
                    // Общая ширина всех элементов управления.
                    allSize = GetSize(m_TabSplitter) - m_TabSplitter.Interval * (m_TabSplitter.Controls.Count - 1);
                    // Нормирующий размер (Новый размер добавляемого контрола).
					if (m_TabSplitter.Controls.Count > 1)
					{
                        // Если нужно установить усреднённый размер элемента управления...
                        if (m_TabSplitter.DefaultSizeForAddedControl == DefaultSize.Average)
                        {
                            normSize = allSize / (m_TabSplitter.Controls.Count - 1);
                        }
                        else
                        {
                            normSize = GetSize(addedCtrl);
                        }
                        // Новая общая ширина всех элементов управления.
                        newSize = allSize + normSize;
					}
					else
					{
						normSize = allSize;
                        // Новая общая ширина всех элементов управления.
                        newSize = allSize;
					}
                    alphaSum = 0;
                    // Пересчитываем в цикле все размеры элементов управления и коефициенты.
                    for (int i = 0; i < m_TabSplitter.Controls.Count; i++)
                    {
                        ctrl = (Cerebrum.Direct3D.Forms.Control)m_TabSplitter.Controls[i];
                        if (addedCtrl != ctrl)
                        {
                            amount = GetSize(ctrl) / newSize;
                            (this[i] as ControlSettings).Amount = amount;
                        }
                        else
                        {
                            amount = normSize / newSize;
                            this.Add(new ControlSettings(ctrl, amount));
                        }
                        alphaSum += amount;
                    }
                    // Поправка.
                    amendment = (1 - alphaSum) / this.Count;
                    position = 0;
                    for (int i = 0; i < this.Count; i++)
                    {
                        // Задаём минимальный размер контрола по умолчанию.
                        (this[i] as ControlSettings).MinSize = m_TabSplitter.Interval;
                        // Получаем элемент управления.
                        ctrl = (Cerebrum.Direct3D.Forms.Control)m_TabSplitter.Controls[i];
                        // Корректируем коэфициент.
                        amount = (this[i] as ControlSettings).Amount + amendment;
                        // Запоминаем новый коэфициент.
                        (this[i] as ControlSettings).Amount = amount;
                        // Считаем размер элемента управления.
                        ctrlSize = amount * allSize;
                        // Устанавливаем элемент управления в нужную позицию и с заданным размером.
                        SetBounds(ctrl, position, ctrlSize);
                        // Позиция для следующего контрола.
                        position += ctrlSize + m_TabSplitter.Interval;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "RecalcAddControl");
                }
            }

            /// <summary>
            /// Пересчёт размеров и коефициентов элементов управления после удаления элемента управления.
            /// </summary>
            /// <param name="removedCtrl"></param>
            public void RecalcRemoveControl(Cerebrum.Direct3D.Forms.Control removedCtrl)
            {
                float allSize;
                float normSize;
                float amount;
                float alphaSum;
                float newSize;
                float ctrlSize;
                float position;
                float amendment;
                Cerebrum.Direct3D.Forms.Control ctrl;

                try
                {
                    this.Remove(removedCtrl);
                    // Общая ширина всех элементов управления.
                    allSize = GetSize(m_TabSplitter) - m_TabSplitter.Interval * (m_TabSplitter.Controls.Count - 1);
                    // Нормирующий размер (Новый размер добавляемого контрола).
                    normSize = GetSize(removedCtrl);
                    // Новая общая ширина всех элементов управления.
                    newSize = allSize - normSize;
                    // Пересчитываем в цикле все размеры элементов управления и коефициенты.
                    alphaSum = 0;
                    for (int i = 0; i < this.Count; i++)
                    {
                        ctrl = (Cerebrum.Direct3D.Forms.Control)m_TabSplitter.Controls[i];
                        amount = GetSize(ctrl) / newSize;
                        (this[i] as ControlSettings).Amount = amount;
                        alphaSum += amount;
                    }
                    // Поправка.
                    amendment = (1 - alphaSum) / this.Count;
                    position = 0;
                    for (int i = 0; i < this.Count; i++)
                    {
                        ctrl = (Cerebrum.Direct3D.Forms.Control)m_TabSplitter.Controls[i];
                        amount = (this[i] as ControlSettings).Amount + amendment;
                        (this[i] as ControlSettings).Amount = amount;
                        ctrlSize = amount * allSize;
                        // Устанавливаем элемент управления в нужную позицию и с заданным размером.
                        SetBounds(ctrl, position, ctrlSize);
                        // Позиция для следующего контрола.
                        position += ctrlSize + m_TabSplitter.Interval;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "RecalcRemoveControl");
                }
            }

            /// <summary>
            /// Пересчитывает коэфициенты всех элементов управления.
            /// </summary>
            public void RecalcAllControls()
            {
                float allSize;
                float amount;
                ControlSettings cs;

                for (int i = 0; i < this.Count; i++)
                {
                    cs = (ControlSettings)this[i];
                    // Общая ширина всех элементов управления.
                    allSize = GetSize(m_TabSplitter) - m_TabSplitter.Interval * (m_TabSplitter.Controls.Count - 1);
                    // Вычисляем коефициент.
                    amount = GetSize(cs.Control) / allSize;
                    // Запоминаем коэфициент.
                    (this[i] as ControlSettings).Amount = amount;
                }
            }

            /// <summary>
            /// Ресайз всего сплитера.
            /// </summary>
            public void ResizeTabSplitter()
            {
                Cerebrum.Direct3D.Forms.Control ctrl;
                ControlSettings cs;
                float ctrlSize;
                float allSize;
                float position;
                float minSizeTS;

                position = 0;
                // Минимальный размер TabSplitter-а.
                minSizeTS = TabSplitterMinSize();
                // Общая ширина всех элементов управления.
                allSize = GetSize(m_TabSplitter) - m_TabSplitter.Interval * (m_TabSplitter.Controls.Count - 1);
                for (int i = 0; i < m_TabSplitter.Controls.Count; i++)
                {
                    ctrl = (Cerebrum.Direct3D.Forms.Control)m_TabSplitter.Controls[i];
                    cs = (ControlSettings)this[i];
                    ctrlSize = cs.Amount * allSize;
                    // Если расчётный размер меньше минимального...
                    if (ctrlSize < cs.MinSize)
                    {
                        // Размер элемента управления устанавливаем в минимальный.
                        ctrlSize = cs.MinSize;
                        // Если минимальный размер TabSplitter-а меньше чем позиция элемента управления плюс его размер...
                        if (minSizeTS < position + ctrlSize)
                        {
                            // Посылаем событие.
                            ControlPositionEventHandler hCtrlPos = (ControlPositionEventHandler)m_TabSplitter.m_Events[TabSplitter.ControlPositionEvent];
                            if (hCtrlPos != null)
                            {
                                hCtrlPos(this, new ControlPositionEventArgs(minSizeTS));
                                // Пересчитываем минимальный размер TabSplitter-а. Может он был изменён.
                                minSizeTS = TabSplitterMinSize();
                            }
                        }
                    }
                    // Устанавливаем элемент управления в нужную позицию и с заданным размером.
                    SetBounds(ctrl, position, ctrlSize);
                    // Позиция для следующего контрола.
                    position += ctrlSize + m_TabSplitter.Interval;
                }
            }

            /// <summary>
            /// Пересчёт размеров при смещении сплитера в какую либо сторону
            /// </summary>
            /// <param name="numSplitter">Номер сплитера</param>
            /// <param name="mousePos">Позиция мышки</param>
            /// <param name="offset">Смещение мышки относительно начала сплитера</param>
            /// <param name="recalcOnly">true - только пересчёт</param>
            /// <returns>true - пересчёт прошёл удачно</returns>
            public bool Recalc(int numSplitter, float mousePos, float offset, bool recalcOnly)
            {
                ControlSettings cs;
                bool f1 = false;
                bool f2 = false;
                float d;
                bool res = false;
                bool res1 = false;
                bool res2 = false;

                if ((numSplitter >= 0) && (numSplitter < this.Count - 1))
                {
                    res = true;
                    cs = (ControlSettings)this[numSplitter];
                    float leftEdge = mousePos - offset;
                    float s = this.GetSize(cs.Control);
                    float l = this.GetPosition(cs.Control);
                    float newSize = leftEdge - l;
                    if (newSize < cs.MinSize)
                    {
                        l -= (cs.MinSize - newSize);
                        newSize = cs.MinSize;
                        f1 = true;
                    }
                    if (recalcOnly == false)
                    {
                        this.SetBounds(cs.Control, l, newSize);
                    }
                    if (f1 == true)
                    {
                        res1 = Recalc(numSplitter - 1, mousePos - cs.MinSize - m_TabSplitter.Interval - offset, 0, recalcOnly);
                        res = res1;
                    }

                    cs = (ControlSettings)this[numSplitter + 1];
                    float rightEdge = leftEdge + this.m_TabSplitter.Interval;
                    s = this.GetSize(cs.Control);
                    l = this.GetPosition(cs.Control);
                    float r = l + s;
                    newSize = r - rightEdge;
                    d = 0;
                    if (newSize < cs.MinSize)
                    {
                        d = (cs.MinSize - newSize);
                        newSize = cs.MinSize;
                        rightEdge = r - newSize;
                        f2 = true;
                    }
                    if (recalcOnly == false)
                    {
                        this.SetBounds(cs.Control, rightEdge + d, newSize);
                    }
                    if (f2 == true)
                    {
                        res2 = Recalc(numSplitter + 1, mousePos + cs.MinSize + m_TabSplitter.Interval - offset, 0, recalcOnly);
                        res = res & res2;
                    }
                }
                else
                {
                    res = false;
                    // Корректируем переход за левую сторону.
                    if (mousePos < 0)
                    {
                        mousePos = 0;
                        //for (int i = 0; i < this.Count - 1; i++)
                        for (int i = 0; i < numSplitter; i++)
                        {
                            cs = (ControlSettings)this[i];
                            this.SetBounds(cs.Control, mousePos, cs.MinSize);
                            mousePos += cs.MinSize + m_TabSplitter.Interval;
                        }
                        if (numSplitter == this.Count - 1)
                        {
                            cs = (ControlSettings)this[this.Count - 1];
                            this.SetBounds(cs.Control, mousePos, GetSize(m_TabSplitter) - mousePos);
                        }
                    }
                    // Корректируем переход за правую сторону.
                    if (mousePos > GetSize(m_TabSplitter))
                    {
                        mousePos = 0;
                        float allMinSize = 0;
                        //for (int i = 1; i < this.Count; i++)
                        for (int i = numSplitter + 1; i < this.Count; i++)
                        {
                            cs = (ControlSettings)this[i];
                            allMinSize += cs.MinSize + m_TabSplitter.Interval;
                        }
                        if (numSplitter == 0)
                        {
                            cs = (ControlSettings)this[0];
                            this.SetBounds(cs.Control, mousePos, GetSize(m_TabSplitter) - allMinSize);
                        }
                        mousePos = GetSize(m_TabSplitter) - allMinSize + m_TabSplitter.Interval;
                        //for (int i = 1; i < this.Count; i++)
                        for (int i = numSplitter + 1; i < this.Count; i++)
                        {
                            cs = (ControlSettings)this[i];
                            this.SetBounds(cs.Control, mousePos, cs.MinSize);
                            mousePos += cs.MinSize + m_TabSplitter.Interval;
                        }
                    }
                }
                return res1 | res2 | res;
            }

            /// <summary>
            /// Возвращает минимальный размер TabSplitter-а.
            /// </summary>
            /// <returns></returns>
            public float TabSplitterMinSize()
            {
                ControlSettings cs;
                float res = 0;

                for (int i = 0; i < this.Count; i++)
                {
                    cs = (ControlSettings)this[i];
                    res += cs.MinSize + m_TabSplitter.Interval;
                }
                res -= m_TabSplitter.Interval;
                return res;
            }

            /// <summary>
            /// Суммарный размер всех элементов управления в TabSplitter-е.
            /// </summary>
            public float TotalSize
            {
                get
                {
                    return GetSize(m_TabSplitter) - m_TabSplitter.Interval * (m_TabSplitter.Controls.Count - 1);
                }
            }
        }
        #endregion

        #region Переменные
        private LayoutDirection m_Direction;
        private float m_Interval;
        private int m_SplitterIndex;
        private TabSplitter.ControlsList m_ControlsList;
        private float m_Offset;
        private DefaultSize m_DefaultSizeForAddedControl;
        #endregion

        #region Конструктор
        /// <summary>
        /// Конструктор.
        /// </summary>
        public TabSplitter()
        {
            m_SplitterIndex = 0;
            m_Interval = 4;
            m_DefaultSizeForAddedControl = DefaultSize.Average;
            m_Direction = LayoutDirection.Horizontal;
            m_ControlsList = new TabSplitter.ControlsList(this);
            this.MouseMove += new MouseEventHandler(TabSplitter_MouseMove);
            this.MouseDown += new MouseEventHandler(TabSplitter_MouseDown);
            this.MouseUp += new MouseEventHandler(TabSplitter_MouseUp);
            this.ControlAdded += new Cerebrum.Direct3D.Forms.ControlEventHandler(TabSplitter_ControlAdded);
            this.ControlRemoved += new Cerebrum.Direct3D.Forms.ControlEventHandler(TabSplitter_ControlRemoved);
            this.Cursor = System.Windows.Forms.Cursors.SizeWE;
        }
        #endregion

        #region Обработчики событий
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TabSplitter_MouseUp(object sender, MouseEventArgs e)
        {
            // Пересчитываем коэфициенты всех элементов управления.
            m_ControlsList.RecalcAllControls();
            // Перерисовываем TabSplitter.
            this.Invalidate();
        }

        /// <summary>
        /// Нажатие кнопки мышки
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TabSplitter_MouseDown(object sender, MouseEventArgs e)
        {
            float sumSize;
            float mouse;

            try
            {
                // Положение курсора мышки.
                if (m_Direction == LayoutDirection.Vertical)
                {
                    mouse = e.Y;
                }
                else
                {
                    mouse = e.X;
                }
                // Ищем нужный сплитер.
                sumSize = 0;
                for (int i = 0; i < this.Controls.Count - 1; i++)
                {
                    sumSize += m_ControlsList.GetSize(this.Controls[i]) + m_Interval;
                    // Если положение курсора находится между 2-мя элементами управления...
                    if ((sumSize - m_Interval <= mouse) && (sumSize >= mouse))
                    {
                        // Запоминаем номер передвигаемого сплитера.
                        m_SplitterIndex = i;
                        m_Offset = mouse - sumSize + m_Interval;
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "TabSplitter_MouseDown");
            }
        }

        /// <summary>
        /// Перемещение курсора мышки
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TabSplitter_MouseMove(object sender, MouseEventArgs e)
        {
            float mouse;
            bool res;

            // Если при передвижении мыши была нажата левая кнопка мыши...
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                // Положение курсора мышки.
                if (m_Direction == LayoutDirection.Vertical)
                {
                    mouse = e.Y;
                }
                else
                {
                    mouse = e.X;
                }
                if (mouse < 0)
                {
                    mouse = 0;
                }
                if (mouse > m_ControlsList.GetSize(this))
                {
                    mouse = m_ControlsList.GetSize(this);
                }
                res = m_ControlsList.Recalc(m_SplitterIndex, mouse, m_Offset, true);
                if (res == true)
                {
                    m_ControlsList.Recalc(m_SplitterIndex, mouse, m_Offset, false);
                }
            }
            this.Invalidate();
        }

        /// <summary>
        /// Удаление элемента управления из сплитера
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TabSplitter_ControlRemoved(object sender, Cerebrum.Direct3D.Forms.ControlEventArgs e)
        {
            m_ControlsList.RecalcRemoveControl(e.Control);
        }

        /// <summary>
        /// Добавление элемента управления в сплитер
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TabSplitter_ControlAdded(object sender, Cerebrum.Direct3D.Forms.ControlEventArgs e)
        {
            m_ControlsList.RecalcAddControl(e.Control);
        }
        #endregion

        #region Override функции
        /// <summary>
        /// Изменение размеров сплитера.
        /// </summary>
        /// <param name="e"></param>
        protected internal override void OnResize(System.EventArgs e)
        {
            base.OnResize(e);
            m_ControlsList.ResizeTabSplitter();
        }

        protected override void OnRenderScene(RenderEventArgs e)
        {
            RectangleF rect;
            Cerebrum.Direct3D.Forms.Control ctrl;

            // Перебираем в цикле все сплитеры
            for (int i = 0; i < this.Controls.Count - 1; i++)
            {
                ctrl = this.Controls[i];
                // Посылаем событие.
                RenderSplitterEventHandler hSplitter = (RenderSplitterEventHandler)this.m_Events[TabSplitter.RenderSplitterEvent];
                if (hSplitter != null)
                {
					System.Drawing.PointF location = ctrl.Location;
					System.Drawing.SizeF size = ctrl.Size;
					System.Drawing.RectangleF clientRect = this.ClientRectangle;
					if (this.m_Direction == LayoutDirection.Horizontal)
					{
						rect = new RectangleF(location.X + size.Width - 0.5f, clientRect.Y, this.m_Interval, clientRect.Height);
					}
					else
					{
						rect = new RectangleF(clientRect.X, location.Y + size.Height - 0.5f, clientRect.Width, this.m_Interval);
					}
                    hSplitter(this, new RenderSplitterEventArgs(e.Device, e.ClipRectangle, i, rect));
                }
            }
            base.OnRenderScene(e);
        }

        protected override void OnUpdateScene(DeviceEventArgs e)
        {
            RectangleF rect;
            Cerebrum.Direct3D.Forms.Control ctrl;

            // Перебираем в цикле все сплитеры
            for (int i = 0; i < this.Controls.Count - 1; i++)
            {
                ctrl = this.Controls[i];
                // Посылаем событие.
                UpdateSplitterEventHandler hSplitter = (UpdateSplitterEventHandler)this.m_Events[TabSplitter.UpdateSplitterEvent];
                if (hSplitter != null)
                {
					System.Drawing.PointF location = ctrl.Location;
					System.Drawing.SizeF size = ctrl.Size;
					System.Drawing.RectangleF clientRect = this.ClientRectangle;
					if (this.m_Direction == LayoutDirection.Horizontal)
					{
						rect = new RectangleF(location.X + size.Width, clientRect.Y, this.m_Interval, clientRect.Height);
					}
					else
					{
						rect = new RectangleF(clientRect.X, location.Y + size.Height, clientRect.Width, this.m_Interval);
					}
					hSplitter(this, new UpdateSplitterEventArgs(e.Device, i, rect));
                }
            }
            base.OnUpdateScene(e);
        }
        #endregion

        #region События
        protected internal static readonly object RenderSplitterEvent = new object();

        public event Cerebrum.Direct3D.Forms.RenderSplitterEventHandler RenderSplitter
        {
            add { this.m_Events.AddHandler(RenderSplitterEvent, value); }
            remove { this.m_Events.RemoveHandler(RenderSplitterEvent, value); }
        }

        protected internal static readonly object UpdateSplitterEvent = new object();

        public event Cerebrum.Direct3D.Forms.UpdateSplitterEventHandler UpdateSplitter
        {
            add { this.m_Events.AddHandler(UpdateSplitterEvent, value); }
            remove { this.m_Events.RemoveHandler(UpdateSplitterEvent, value); }
        }

        protected internal static readonly object ControlPositionEvent = new object();

        public event Cerebrum.Direct3D.Forms.ControlPositionEventHandler ControlPosition
        {
            add { this.m_Events.AddHandler(ControlPositionEvent, value); }
            remove { this.m_Events.RemoveHandler(ControlPositionEvent, value); }
        }
        #endregion

        #region Публичные свойства и методы
        /// <summary>
        /// Задаёт минимальный размер для выбранного элемента управления
        /// </summary>
        /// <param name="ctrl">Элемент управления</param>
        /// <param name="minSize">Минимальный размер</param>
        /// <returns>false, если не удалось найти элемент управления</returns>
        public bool SetControlMinSize(Cerebrum.Direct3D.Forms.Control ctrl, float minSize)
        {
            bool res = false;

            for (int i = 0; i < m_ControlsList.Count; i++)
            {
                if ((m_ControlsList[i] as ControlSettings).Control == ctrl)
                {
                    (m_ControlsList[i] as ControlSettings).MinSize = minSize;
                    res = true;
                    break;
                }
            }
            return res;
        }

        /// <summary>
        /// Интервал между элементами управления. Ширина сплиттера.
        /// </summary>
        [
            Category("Settings"),
            DefaultValue(0)
        ]
        public float Interval
        {
            set
            {
                m_Interval = value;
                if (m_Interval < 5)
                {
                    m_Interval = 5;
                }
            }
            get
            {
                return m_Interval;
            }
        }

        /// <summary>
        /// Направление сплитинга
        /// </summary>
        [
            Category("Direction"),
            DefaultValue(LayoutDirection.Horizontal),
            Description("")
        ]
		public LayoutDirection LayoutDirection
        {
            set
            {
                m_Direction = value;
                m_ControlsList.ResizeTabSplitter();
            }
            get
            {
                return m_Direction;
            }
        }

        /// <summary>
        /// Размер добавляемого элемента управления по умолчанию.
        /// </summary>
        [
            Category("Settings"),
            DefaultValue(DefaultSize.Average)
        ]
        public DefaultSize DefaultSizeForAddedControl
        {
            set
            {
                m_DefaultSizeForAddedControl = value;
            }
            get
            {
                return m_DefaultSizeForAddedControl;
            }
        }
        #endregion
    }        
}
